<?php
/*
 * Copyright (c) 2008 Sergey Bondari, bondari@bondari.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

namespace Mosaic\System;


/**
 * Tile processing resource implementation
 *
 * @package System
 * @subpackage Resources
 */
class Tile extends Resource implements ifTile {

	/**
	 * DOM node of the Active XML tag
	 * @var DOMElement
	 */
	private $domNode;

	/**
	 * Array of attrubutes
	 * @var array
	 */
	private $attributes;


	/**
	 * Tile name
	 * @var string
	 */
	private $tagName;


	/**
	 * Processed XML
	 * @var string
	 */
	private $parsedXML;

	/**
	 * Constructor
	 * Initializes local data from parameter.
	 * @param mixed Tile element, can be instance of DOMDocument, DOMElement or simply an XML fragment
	 */
	function __construct($tile) {
		parent::__construct();


		if ($tile instanceof \DOMDocument) { // tile is DOMDocument
			$this->domNode = $tile->documentElement;
		} else if ($tile instanceof \DOMElement) { // tile is DOMElement
			$this->domNode = $tile;
		} else if (is_string($tile)) { // tile is string XML fragment
			$domDoc = \DOMDocument::loadXML($tile);
			$this->domNode = $domDoc->documentElement;
		}

		if (! $this->domNode instanceof \DOMElement) {
			throw new RuntimeException('Unexpected tile data. Invalid DOM or XML.');
		}

		if ($this->domNode->namespaceURI != NS_TILE) {
			throw new RuntimeException('Tiles must have '.NS_TILE.' namespace');
		}


		$this->tagName = $this->domNode->localName;
		$this->attributes = array();
		foreach ($this->domNode->attributes as $k => $v) $this->attributes[$k] = $v->value;
		$this->parsedXML = '';
	}


	/**
	 * Tile tagname getter
	 * Returns an tile tag name
	 * @return string tag name
	 */
	public function getTagName() {
		return $this->tagName;
	}


	/**
	 * Returns the tile attributes
	 * @return array
	 */
	public function getAttributes() {
		return $this->attributes;
	}

	/**
	 * Sets parsed data from XML
	 * @param string
	 */
	public function setParsedXML($xml) {
		$this->parsedXML .= $xml;
	}

	/**
	 * Returns parsed data 
	 * @return string
	 */
	public function getParsedXML() {
		return $this->parsedXML;
	}


	/**
	 * Sets parsed data from XML
	 * @param string
	 */
	public function getXML() {
		$xml = $this->domNode->ownerDocument->saveXML($this->domNode);
		return $xml;
	}

	/**
	 * Sets parsed data from XML
	 * @param string
	 */
	public function getDOM() {
		return $this->domNode;
	}


	/**	
	 * Tiles uniting.
	 * Tiles are processed asynchronously and in parallel, thus require to implement merginig routine for ICC to call.
	 * This  tile implementation concatenates XML fragments produced by components.
	 *
	 * @param Tile Tile to merge with.
	 * @return void
	 */
	public function merge($res) {
		$this->setParsedXML($res->getParsedXML());
	}


	/**	
	 * Tile serialization.
	 * 
	 * Due to the fact that PHP is unable to serialize DOM objects, tiles serialization routine natively serialized DOM objects as XML.
	 *
	 * @return string Serialized data
	 */
	public function __serialize() {
		if (!$this->domNode->getAttribute('xmlns:'.$this->domNode->prefix)) {
			$attr = $this->domNode->ownerDocument->createAttribute('xmlns:'.$this->domNode->prefix);
			$attr->value = NS_TILE;
			$this->domNode->appendChild($attr);
		}

		return serialize(array('xml' => $this->getXML(), 'parsed' => $this->getParsedXML()));
	}

	/**	
	 * Tiles deserialization.
	 * 
	 * @param string Serialized data
	 * @return Tile
	 */
	static public function __deserialize($string) {
		$data = unserialize($string);
		$tile = new Tile($data['xml']);
		$tile->setParsedXML($data['parsed']);
		return $tile;
	}
}
